package com.linh.web.spring;

import java.util.Properties;

import javax.sql.DataSource;
import javax.transaction.TransactionManager;

import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
import org.hibernate.tool.hbm2ddl.Target;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;

@Configuration
public abstract class DatabaseSpring {

	@Bean
	public LocalSessionFactoryBean localSessionFactoryBean() {
		LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
		localSessionFactoryBean.setDataSource(dataSource());

		localSessionFactoryBean.setAnnotatedClasses(domainClasses());

		Properties hibernateProperties = new Properties();
		hibernateProperties
				.setProperty("hibernate.dialect", hibernateDialect());
		localSessionFactoryBean.setHibernateProperties(hibernateProperties);

		return localSessionFactoryBean;
	}

	@Bean
	public SessionFactory sessionFactory() {
		return localSessionFactoryBean().getObject();
	}

	@Bean
	public HibernateTransactionManager hibernateTransactionManager() {
		HibernateTransactionManager transactionManager = new HibernateTransactionManager();
		transactionManager.setSessionFactory(sessionFactory());
		return transactionManager;
	}

	final protected void configureDataSource(BasicDataSource dataSource) {
		// TODO fill in
	}

	static void schemaUpgrade(org.hibernate.cfg.Configuration configuration) {
		SchemaUpdate schemaUpdate = new SchemaUpdate(configuration);
		schemaUpdate.execute(true, true);
	}

	static void applySchema(org.hibernate.cfg.Configuration configuration) {
		SchemaExport schemaExport = new SchemaExport(configuration);
		schemaExport.execute(Target.BOTH, SchemaExport.Type.BOTH);
	}

	@Bean
	abstract org.hibernate.cfg.Configuration configuration();

	abstract DataSource dataSource();

	abstract String hibernateDialect();

	static Class<?>[] domainClasses() {
		return new Class<?>[] {};
	}

}
